##
# Replication for Breaking the Cabinet's Glass Ceiling: The Gendered Effect of Political Experience in Presidential Democracies
##

# Don S. Lee and Charles T. McClean
# Comparative Political Studies Dataverse

##
# Packages
##

library(stargazer)
library(lfe)
library(MatchIt)
library(margins)
library(prediction)
library(multiwayvcov)
library(arm)
library(estimatr)
library(tidyverse)
library(modelsummary)
library(flextable)

##
# Data
##

data <- read.csv("ministers.csv")

##
# FIGURE 1: CABINET CAREERS BY GENDER AND POLITICAL EXPERIENCE
##

career <- data %>%
  count(gender,insider,nextjob) %>%
  group_by(gender, insider) %>%
  mutate(pct = n / sum(n) * 100,
         Insider = ifelse(insider == 1, "Political Insider", "Political Outsider"),
         Gender = ifelse(gender == 1, "Female Minister", "Male Minister"))
career2 <- data %>%
  count(gender,nextjob) %>%
  group_by(gender) %>%
  mutate(pct = n / sum(n) * 100,
         Insider = "Overall",
         insider = NA,
         Gender = ifelse(gender == 1, "Female Minister", "Male Minister"))
career <- bind_rows(career, career2)

career$Insider <- factor(career$Insider,
                         levels = c("Political Outsider", "Political Insider", "Overall"))
career$nextjob <- factor(career$nextjob,
                         levels = c("Promotion", "Retention", "Demotion", "Exit"))
career <- arrange(career, gender, insider, nextjob)
career <- career %>%
  group_by(Insider, Gender) %>%
  mutate(lab_ypos = 100 - (cumsum(pct) - pct * .5))

ggplot(career, aes(y = pct, x = Insider)) +
  scale_fill_grey(start = 0.5, end = 0.8, guide = guide_legend(reverse = TRUE)) +
  geom_col(aes(fill = nextjob)) +
  coord_flip() +
  theme_bw() +
  theme(legend.position = "bottom",
        axis.title.y = element_blank(),
        axis.title.x = element_text(size=10),
        axis.text.y = element_text(size = 10),
        axis.text.x = element_text(size = 10),
        legend.text = element_text(size = 10),
        strip.text = element_text(size=10),
        legend.title = element_blank(),
        plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm")) +
  xlab("") +
  scale_y_continuous(name = "",
                     limits = c(0,100),
                     expand=c(0,0),
                     labels = c("0%", "25%", "50%", "75%", "100%")) +
  geom_text(aes(y = lab_ypos, label = paste(as.character(sprintf("%.1f", round(pct,1))), "%", sep=""), group = nextjob), color = "white", size = 3.25) +
  facet_wrap(~Gender, nrow=2)

rm(career, career2)

##
# TABLE 2: CHARACTERISTICS OF CABINET MINISTERS BY GENDER
##

balance <- data %>%
  mutate(appointed = ifelse(insider == 1 & data$pol == 0, 1, 0),
         outsider = ifelse(insider == 0, 1, 0),
         korea = ifelse(country == "korea", 1, 0),
         taiwan = ifelse(country == "taiwan", 1, 0),
         philippines = ifelse(country == "philippines", 1, 0),
         indonesia = ifelse(country == "indonesia", 1, 0),
         Treatment = ifelse(gender == 1, "Female Minister", "Male Minister")) %>%
  select(Treatment,
         `Political Insider` = insider,
         Elected = pol,
         Appointed = appointed,
         Business = business,
         Bureaucrat = bureaucrat,
         Academy = academy,
         Education = educ,
         Age = ageyear,
         Low = low,
         Medium = medium,
         High = high,
         `South Korea` = korea,
         Taiwan = taiwan,
         Philippines = philippines,
         Indonesia = indonesia)

datasummary_balance(~Treatment,
                    data = balance,
                    fmt = 2)

rm(balance)

##
# TABLE 3: POLITICAL EXPERIENCE AND WOMEN'S CAREERS IN CABINET (FIXED EFFECTS DESIGN)
##

models <- list(
  "Exit 1" = felm(exit ~ gender + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Exit 2" = felm(exit ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Demote 1" = felm(demote ~ gender + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Demote 2" = felm(demote ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Retain 1" = felm(retain ~ gender + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Retain 2" = felm(retain ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Promote 1" = felm(promote ~ gender + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data),
  "Promote 2" = felm(promote ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country_post + country_year | 0 | minister, data=data)
)

msummary(models,
         fmt = "%.2f",
         stars = TRUE,
         coef_rename = c("gender" = "Female Minister", "insider" = "Political Insider",
                         "gender:insider" = "Female × Insider"),
         coef_omit = "educ|ageyear|business|bureaucrat|academy",
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|Sigma|Statistics|p")

rm(models)

##
# TABLE 4: POLITICAL EXPERIENCE AND WOMEN'S CAREERS IN CABINET (EXACT MATCHING DESIGN)
##

set.seed(1234)
nearest.match <- matchit(formula = gender ~ countryid + insider + agegroup + educ + business +
                           bureaucrat + academy + low + medium, data=data, method="exact") 
nearest.data <- match.data(nearest.match)

models <- list(
  "Exit 1" = lm(exit ~ gender, data=nearest.data, weights=weights),
  "Exit 2" = lm(exit ~ gender * insider, data=nearest.data, weights=weights),
  "Demote 1" = lm(demote ~ gender, data=nearest.data, weights=weights),
  "Demote 2" = lm(demote ~ gender * insider, data=nearest.data, weights=weights),
  "Retain 1" = lm(retain ~ gender, data=nearest.data, weights=weights),
  "Retain 2" = lm(retain ~ gender * insider, data=nearest.data, weights=weights),
  "Promote 1" = lm(promote ~ gender, data=nearest.data, weights=weights),
  "Promote 2" = lm(promote ~ gender * insider, data=nearest.data, weights=weights)
)

msummary(models,
         fmt = 2,
         stars = TRUE,
         coef_map = c("gender" = "Female Minister",
                      "insider" = "Political Insider",
                      "gender:insider" = "Female × Insider",
                      "(Intercept)" = "Intercept"),
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|R2|Sigma|Statistics|p|F")

rm(models, nearest.data, nearest.match)

##
# FIGURE 2: MARGINAL EFFECT OF POLITICAL EXPERIENCE ON PROMOTION BY GENDER
##

# Promotion
promotion <- summary(margins(models[[8]], variables="insider", at=list(gender=0:1)))

# Table
mplot <- data.frame(matrix(NA, nrow = 2, ncol = 5))
colnames(mplot) <- c("dv", "gender", "ame", "lower", "upper")
mplot$dv <- c("Cabinet Promotion", "Cabinet Promotion")
mplot$gender <- c("Male Minister", "Female Minister")
mplot$ame <- promotion$AME
mplot$lower <- promotion$lower
mplot$upper <- promotion$upper

ggplot(data = mplot, aes(ame, gender)) +
  geom_point(na.rm=T) +
  geom_errorbarh(aes(xmin = lower, xmax = upper),
                 height = 0,
                 na.rm = T) +
  geom_vline(xintercept = 0) +
  theme_bw() +
  ylab("") +
  scale_x_continuous(limits=c(-0.2, 0.4),
                     breaks=seq(-0.2, 0.4, 0.1),
                     name = "Marginal Effect of Political Experience on Cabinet Promotion") +
  theme(plot.margin = unit(c(0.5,0.5,0.5,0.5), "cm"),
        axis.title.y = element_blank(),
        axis.title.x = element_text(size=10),
        axis.text.y = element_text(size = 10),
        axis.text.x = element_text(size = 10),
        legend.text = element_text(size = 10),
        strip.text = element_text(size=10)) 

rm(nearest.data, nearest.match, models, promotion, mplot)

############
# APPENDIX #
############

##
# TABLE A1: Descriptive Statistics
##

desc <- data %>%
  mutate(appointed = ifelse(insider == 1 & data$pol == 0, 1, 0),
         korea = ifelse(country == "korea", 1, 0),
         taiwan = ifelse(country == "taiwan", 1, 0),
         philippines = ifelse(country == "philippines", 1, 0),
         indonesia = ifelse(country == "indonesia", 1, 0)) %>%
  select(`Female Minister` = gender,
         `Political Insider` = insider,
         Elected = pol,
         Appointed = appointed,
         Business = business,
         Bureaucrat = bureaucrat,
         Academy = academy,
         Education = educ,
         Age = ageyear,
         `Age Group` = agegroup,
         Low = low,
         Medium = medium,
         High = high,
         `South Korea` = korea,
         Taiwan = taiwan,
         Philippines = philippines,
         Indonesia = indonesia)

datasummary(`Female Minister` + `Political Insider` + Elected + Appointed +
              Business + Bureaucrat + Academy +
              Education + Age + `Age Group` + Low + Medium + High + `South Korea` +
              Taiwan + Philippines + Indonesia ~ mean + sd + min + max,
            data = desc,
            fmt = 2)

rm(desc)

##
# TABLE A2: MINISTER GENDER AND EXPERIENCE BY COUNTRY AND ADMINISTRATION
##

# By Country (Total)
summary <- data %>%
  group_by(country) %>%
  summarize(start = as.character(min(year)),
            end = as.character(max(year)),
            female_insider = length(gender[gender == 1 & insider == 1]),
            female_outsider = length(gender[gender == 1 & insider == 0]),
            female_total = length(gender[gender == 1]),
            male_insider = length(gender[gender == 0 & insider == 1]),
            male_outsider = length(gender[gender == 0 & insider == 0]),
            male_total = length(gender[gender == 0]))
flextable(summary)

# By Administration (Total)
summary2 <- data %>%
  mutate(syear = as.numeric(substr(as.character(data$start), nchar(as.character(data$start)) - 3, nchar(as.character(data$start)))),
         eyear = as.numeric(substr(as.character(data$end), nchar(as.character(data$end)) - 3, nchar(as.character(data$end))))) %>%
  group_by(country, admin) %>%
  summarize(start = min(syear),
            end = max(eyear),
            female_insider = length(gender[gender == 1 & insider == 1]),
            female_outsider = length(gender[gender == 1 & insider == 0]),
            female_total = length(gender[gender == 1]),
            male_insider = length(gender[gender == 0 & insider == 1]),
            male_outsider = length(gender[gender == 0 & insider == 0]),
            male_total = length(gender[gender == 0])) %>%
  arrange(country, start) %>%
  mutate(start = as.character(start),
         end = as.character(end))
flextable(summary2)

# By Country (Unique)
summary <- data %>%
  group_by(country) %>%
  summarize(start = as.character(min(year)),
            end = as.character(max(year)),
            female_insider = length(unique(minister[gender == 1 & insider == 1])),
            female_outsider = length(unique(minister[gender == 1 & insider == 0])),
            female_total = length(unique(minister[gender == 1])),
            male_insider = length(unique(minister[gender == 0 & insider == 1])),
            male_outsider = length(unique(minister[gender == 0 & insider == 0])),
            male_total = length(unique(minister[gender == 0])))
flextable(summary)

# By Administration (Unique)
summary2 <- data %>%
  mutate(syear = as.numeric(substr(as.character(data$start), nchar(as.character(data$start)) - 3, nchar(as.character(data$start)))),
         eyear = as.numeric(substr(as.character(data$end), nchar(as.character(data$end)) - 3, nchar(as.character(data$end))))) %>%
  group_by(country, admin) %>%
  summarize(start = min(syear),
            end = max(eyear),
            female_insider = length(unique(minister[gender == 1 & insider == 1])),
            female_outsider = length(unique(minister[gender == 1 & insider == 0])),
            female_total = length(unique(minister[gender == 1])),
            male_insider = length(unique(minister[gender == 0 & insider == 1])),
            male_outsider = length(unique(minister[gender == 0 & insider == 0])),
            male_total = length(unique(minister[gender == 0]))) %>%
  arrange(country, start) %>%
  mutate(start = as.character(start),
         end = as.character(end))
flextable(summary2)

rm(summary, summary2)

##
# TABLE A3: POLITICAL INSIDERS BY GENDER AND BACKGROUND
##

# Total
insiders <- data %>%
  filter(insider == 1) %>%
  group_by(country) %>%
  summarize(female_elected = length(gender[gender == 1 & pol == 1]),
            female_appointed = length(gender[gender == 1 & pol == 0]),
            female_total = length(gender[gender == 1]),
            male_elected = length(gender[gender == 0 & pol == 1]),
            male_appointed = length(gender[gender == 0 & pol == 0]),
            male_total = length(gender[gender == 0]))
flextable(insiders)

# Unique
insiders <- data %>%
  filter(insider == 1) %>%
  group_by(country) %>%
  summarize(female_elected = length(unique(minister[gender == 1 & pol == 1])),
            female_appointed = length(unique(minister[gender == 1 & pol == 0])),
            female_total = length(unique(minister[gender == 1])),
            male_elected = length(unique(minister[gender == 0 & pol == 1])),
            male_appointed = length(unique(minister[gender == 0 & pol == 0])),
            male_total = length(unique(minister[gender == 0])))
flextable(insiders)

##
# TABLE A4: POLITICAL OUTSIDERS BY GENDER AND BACKGROUND
##

# Total
outsiders <- data %>%
  filter(insider == 0) %>%
  group_by(country) %>%
  summarize(female_business = length(gender[gender == 1 & business == 1]),
            female_bureaucrat = length(gender[gender == 1 & bureaucrat == 1]),
            female_academy = length(gender[gender == 1 & academy == 1]),
            female_other = length(gender[gender == 1 & business == 0 & bureaucrat == 0 & academy == 0]),
            female_total = length(gender[gender == 1]),
            male_business = length(gender[gender == 0 & business == 1]),
            male_bureaucrat = length(gender[gender == 0 & bureaucrat == 1]),
            male_academy = length(gender[gender == 0 & academy == 1]),
            male_other = length(gender[gender == 0 & business == 0 & bureaucrat == 0 & academy == 0]),
            male_total = length(gender[gender == 0]))
flextable(outsiders)

# Unique
outsiders <- data %>%
  filter(insider == 0) %>%
  group_by(country) %>%
  summarize(female_business = length(unique(minister[gender == 1 & business == 1])),
            female_bureaucrat = length(unique(minister[gender == 1 & bureaucrat == 1])),
            female_academy = length(unique(minister[gender == 1 & academy == 1])),
            female_other = length(unique(minister[gender == 1 & business == 0 & bureaucrat == 0 & academy == 0])),
            female_total = length(unique(minister[gender == 1])),
            male_business = length(unique(minister[gender == 0 & business == 1])),
            male_bureaucrat = length(unique(minister[gender == 0 & bureaucrat == 1])),
            male_academy = length(unique(minister[gender == 0 & academy == 1])),
            male_other = length(unique(minister[gender == 0 & business == 0 & bureaucrat == 0 & academy == 0])),
            male_total = length(unique(minister[gender == 0])))
flextable(outsiders)

rm(insiders, outsiders)

##
# TABLE A5: FIXED EFFECTS RESULTS WITH LOGISTIC REGRESSION
##

models <- list(
  "Exit 1" = glm(exit ~ gender + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Exit 2" = glm(exit ~ gender * insider + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Demote 1" = glm(demote ~ gender + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Demote 2" = glm(demote ~ gender * insider + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Retain 1" = glm(retain ~ gender + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Retain 2" = glm(retain ~ gender * insider + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Promote 1" = glm(promote ~ gender + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit")),
  "Promote 2" = glm(promote ~ gender * insider + educ + ageyear + business + bureaucrat + academy + factor(country), data=data, family=binomial(link="logit"))
)

msummary(models,
         fmt = 2,
         vcov = "robust",
         cluster = "country",
         coef_map = c("gender" = "Female Minister",
                      "insider" = "Political Insider",
                      "gender:insider" = "Female × Insider",
                      "(Intercept)" = "Intercept"),
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|Sigma|Statistics|p|F|Std. Errors",
         stars = TRUE)

rm(models)

##
# TABLE A6: FIXED EFFECTS RESULTS WITHOUT CONTROL VARIABLES
##

models <- list(
  "Exit 1" = felm(exit ~ gender | country_post + country_year | 0 | minister, data=data),
  "Exit 2" = felm(exit ~ gender * insider | country_post + country_year | 0 | minister, data=data),
  "Demote 1" = felm(demote ~ gender | country_post + country_year | 0 | minister, data=data),
  "Demote 2" = felm(demote ~ gender * insider | country_post + country_year | 0 | minister, data=data),
  "Retain 1" = felm(retain ~ gender | country_post + country_year | 0 | minister, data=data),
  "Retain 2" = felm(retain ~ gender * insider | country_post + country_year | 0 | minister, data=data),
  "Promote 1" = felm(promote ~ gender | country_post + country_year | 0 | minister, data=data),
  "Promote 2" = felm(promote ~ gender * insider | country_post + country_year | 0 | minister, data=data)
)

msummary(models,
         fmt = "%.2f",
         stars = TRUE,
         coef_rename = c("gender" = "Female Minister", "insider" = "Political Insider",
                         "gender:insider" = "Female × Insider"),
         coef_omit = "educ|ageyear|business|bureaucrat|academy",
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|Sigma|Statistics|p")

rm(models)

##
# TABLE A7: FIXED EFFECTS RESULTS WITH ALTERNATIVE FIXED EFFECTS
##

models <- list(
  "Exit 1" = felm(exit ~ gender + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Exit 2" = felm(exit ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Demote 1" = felm(demote ~ gender + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Demote 2" = felm(demote ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Retain 1" = felm(retain ~ gender + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Retain 2" = felm(retain ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Promote 1" = felm(promote ~ gender + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data),
  "Promote 2" = felm(promote ~ gender * insider + educ + ageyear + business + bureaucrat + academy | country + year | 0 | minister, data=data)
)

msummary(models,
         fmt = "%.2f",
         stars = TRUE,
         coef_rename = c("gender" = "Female Minister", "insider" = "Political Insider",
                         "gender:insider" = "Female × Insider"),
         coef_omit = "educ|ageyear|business|bureaucrat|academy",
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|Sigma|Statistics|p")

rm(models)

##
# TABLE A8: MATCHING RESULTS WITH NEAREST NEIGHBOR MATCHING
##

set.seed(1234)
nearest.match <- matchit(formula = gender ~ countryid + insider + ageyear + educ + business +
                           bureaucrat + academy + low + medium, data=data, method="nearest") 
nearest.data <- match.data(nearest.match)

models <- list(
  "Exit 1" = lm(exit ~ gender, data=nearest.data, weights=weights),
  "Exit 2" = lm(exit ~ gender * insider, data=nearest.data, weights=weights),
  "Demote 1" = lm(demote ~ gender, data=nearest.data, weights=weights),
  "Demote 2" = lm(demote ~ gender * insider, data=nearest.data, weights=weights),
  "Retain 1" = lm(retain ~ gender, data=nearest.data, weights=weights),
  "Retain 2" = lm(retain ~ gender * insider, data=nearest.data, weights=weights),
  "Promote 1" = lm(promote ~ gender, data=nearest.data, weights=weights),
  "Promote 2" = lm(promote ~ gender * insider, data=nearest.data, weights=weights)
)

msummary(models,
         fmt = 2,
         stars = TRUE,
         coef_map = c("gender" = "Female Minister",
                      "insider" = "Political Insider",
                      "gender:insider" = "Female × Insider",
                      "(Intercept)" = "Intercept"),
         gof_omit = "DF|Deviance|Log.Lik.|AIC|BIC|R2 Adj.|R2|Sigma|Statistics|p|F")

rm(nearest.match, nearest.data, models)
